package com.grass.cropTradingCenter.handler;

import com.grass.cropTradingCenter.common.BusinessException;
import com.grass.cropTradingCenter.common.LoginInfo;
import com.grass.cropTradingCenter.common.ResultCode;
import com.grass.cropTradingCenter.common.annotation.LoginFree;
import com.grass.cropTradingCenter.utils.SecurityUtils;
import com.grass.cropTradingCenter.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 验证登录的拦截器
 */

@Slf4j
@Component
public class LoginInterceptor extends InterceptorRegistry implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        log.info("===== 进入拦截器 ====");
        // 如果不是映射到方法，可以直接访问
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }


        //放行swagger
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        String knifeString = handlerMethod.getBean().getClass().getName();
        if (knifeString.equals("org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController")
                || knifeString.equals("springfox.documentation.swagger.web.ApiResourceController")) {
            return true;
        }

        // 放行不需要登录的方法
        Method method = handlerMethod.getMethod();
        if(method.isAnnotationPresent(LoginFree.class)){
            LoginFree loginFree = method.getAnnotation(LoginFree.class);
            if(loginFree.status()) return true;
        }

        // 为空则返回错误
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {
            // 未登录
            throw new BusinessException(ResultCode.NO_LOGIN);
        }

        Map<String, String> map = TokenUtil.parseToken(token);

        // 判断是否过期
        String userId = map.get("userId");
        String type = map.get("type");
        long timeOfUse = System.currentTimeMillis() - Long.parseLong(map.get("timeStamp"));

        // 往ThreadLocal放值
        SecurityUtils.setLoginUser(new LoginInfo(Integer.parseInt(userId), type));

        // token验证成功
        if (timeOfUse < TokenUtil.REFRESH_TIME) {
            return true;
        }
        // token 刷新
        else if (timeOfUse < TokenUtil.EXPIRE_TIME) {
            response.setHeader("token", TokenUtil.getToken(userId, type));
            log.info("token 刷新成功");
            return true;
        } else {
            throw new BusinessException(ResultCode.NO_LOGIN);
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 防止内存泄露
        SecurityUtils.clearLoginUser();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
